// C source file with the function definitions to handle BMD's TEX1 section

// check_j3dgraph_bmd_tex1() function
// function to check if the TEX1 section of a BMD is valid
j3dgraph_bmd_tex1_err_cd check_j3dgraph_bmd_tex1(j3dgraph * file)
{
  // check params
  if (file == NULL)
    goto err;
  
  // check the TEX1 character array at section start  
  if (comp_bytes(((j3dgraph_gen_sec *) (file -> SEC)[J3DGRAPH_BMD_TEX1_POS]) -> START,
                 J3DGRAPH_BMD_SEC_START[J3DGRAPH_BMD_TEX1_POS][file -> ENDIAN - 1], 4) == 0)
    goto err;
  
  // TODO: add more checks
  
  // all good
  return J3DGRAPH_BMD_TEX1_ERR_NO_ERR;
  
  // invalid section
  err:
  return J3DGRAPH_BMD_TEX1_ERR_HEADER;
}

// append_j3dgraph_bmd_tex1() function
// append a j3dgraph_bmd_tex1 struct to an incomplete j3dgraph struct
j3dgraph_bmd_tex1 * append_j3dgraph_bmd_tex1(j3dgraph * file)
{  
  // check if the section is valid
  j3dgraph_bmd_tex1 * tex1 = NULL;
  j3dgraph_bmd_tex1_err_cd err_cd = check_j3dgraph_bmd_tex1(file);
  if (err_cd < J3DGRAPH_BMD_TEX1_ERR_NO_ERR)
    goto err;
  
  // otherwise append the structure to j3dgraph
  tex1 = allocate_memory(1, sizeof(j3dgraph_bmd_tex1));
  if (tex1 == NULL)
    goto err;
  
  // fill the structure  
  // tmp variables
  umax tmp = 0;
  j3dgraph_gen_sec * sec = (file -> SEC)[J3DGRAPH_BMD_TEX1_POS];
  byte * ptr = (sec -> START) + 8;
  
  // my additions
  tex1 -> PATH = file -> PATH;
  tex1 -> ENDIAN = file -> ENDIAN;
  tex1 -> ERR_CD = err_cd;
  // actual structure
  tex1 -> START = sec -> START;
  tex1 -> SIZE = sec -> SIZE;  
  tex1 -> TEX_CNT = ptr; ptr += 2;
  tex1 -> UNK_1 = ptr; ptr += 2;
  tex1 -> BTI_HEADER_LIST_OFFSET = ptr; ptr += 4;
  tex1 -> TEX_STR_TB_OFFSET = ptr; ptr += 4;
  
  // get padding length (32)
  tmp = get_j3dgraph_padding_size(ptr - (tex1 -> START), true);
  tex1 -> PAD_1 = ptr; ptr += tmp;
  
  // get texture count
  umax tex_count = get_std_uint(16, tex1 -> TEX_CNT, file -> ENDIAN);
  tex1 -> BTI_HEADER_LIST = ptr; ptr += tex_count * 32;
  tex1 -> BTI_DATA_LIST = ptr; 
  
  // TODO: research the BTI file format
  
  // create the texture string table
  ptr = (tex1 -> START) + get_std_uint(32, tex1 -> TEX_STR_TB_OFFSET, file -> ENDIAN);
  tmp = get_j3dgraph_str_tb_size(ptr, (file -> DATA) + (file -> FSIZE) - ptr, file -> ENDIAN);
  if (tmp == 0)
    goto err;
  tex1 -> TEX_STR_TB = get_j3dgraph_str_tb(ptr, (file -> DATA) + (file -> FSIZE) - ptr, file -> ENDIAN);
  if ((tex1 -> TEX_STR_TB) == NULL)
    goto err;
  ptr += tmp;
  
  // final padding (32)
  tex1 -> PAD_2 = ptr;
  
  // remove the j3dgraph_gen_sec and append the new one
  free_memory((file -> SEC)[J3DGRAPH_BMD_TEX1_POS]);
  return ((file -> SEC)[J3DGRAPH_BMD_TEX1_POS] = tex1);
  // failure
  err:
  free_memory(tex1);
  return NULL;
}

// remove_j3dgraph_bmd_tex1() function
// function to remove a j3dgraph_bmd_tex1 structure from a j3dgraph structure
void remove_j3dgraph_bmd_tex1(j3dgraph * file)
{
  // check params
  if (file == NULL || (file -> SEC) == NULL)
    return;
  // free the memory allocated by append_j3dgraph_bmd_tex1()
  close_j3dgraph_str_tb(((j3dgraph_bmd_tex1 *) (file -> SEC)[J3DGRAPH_BMD_TEX1_POS]) -> TEX_STR_TB);
  free_memory((file -> SEC)[J3DGRAPH_BMD_TEX1_POS]);
  return;
}

// print_j3dgraph_bmd_tex1() function
// print the information of the TEX1 section of a BMD
void print_j3dgraph_bmd_tex1(j3dgraph_bmd_tex1 * tex1)
{
  // check ptr
  if (tex1 == NULL || (tex1 -> ERR_CD) < J3DGRAPH_BMD_TEX1_ERR_NO_ERR)
    return;
  
  // starting visual queue
  printf("\n### J3DGraph TEX1 section info start ###\n\n");
  
  // file info
  printf("File: %s\n", tex1 -> PATH);
  printf("Section endian: %s\n", (tex1 -> ENDIAN) == BIG ? "BIG" : "LITTLE");
  printf("Section error code: %u\n", tex1 -> ERR_CD);
  
  // section header
  printf("\nSection start: ");
  print_ascii_arr(tex1 -> START, 4);
  printf("Section size (bytes): %llu\n", get_std_uint(32, tex1 -> SIZE, tex1 -> ENDIAN));
  
  // get texture count
  umax tex_count = get_std_uint(16, tex1 -> TEX_CNT, tex1 -> ENDIAN);
  printf("Texture count: %llu\n", tex_count);
  printf("TEX1 unknown 1 (hex): %04llX\n", get_std_uint(16, tex1 -> UNK_1, tex1 -> ENDIAN));
  printf("BTI header list offset (hex): %08llX\n",
         get_std_uint(32, tex1 -> BTI_HEADER_LIST_OFFSET, tex1 -> ENDIAN));
  printf("Texture name table offset (hex): %08llX\n",
         get_std_uint(32, tex1 -> TEX_STR_TB_OFFSET, tex1 -> ENDIAN));
  printf("Padding 1: "); // 32 multiple
  print_ascii_arr(tex1 -> PAD_1, get_j3dgraph_padding_size((tex1 -> PAD_1) - (tex1 -> START), true));
  
  // print each BTI header
  byte * ptr = tex1 -> BTI_HEADER_LIST; // tmp pointer
  for (umax i = 0; i < tex_count; i++) {
    printf("# BTI at index %llu header:\n", i);
    print_array(ptr, 16, 1, print_byte_hex);
    print_array(ptr + 16, 16, 1, print_byte_hex);
    ptr += 32;
  }
  
  // TODO: research the BTI file format
  printf("\nBTI file data list size: %u\n", (tex1 -> TEX_STR_TB -> STR_CNT) - (tex1 -> BTI_DATA_LIST));
  
  // texture string table
  printf("\n## Texture string table begin:\n");
  print_j3dgraph_str_tb(tex1 -> TEX_STR_TB);  
  
  // final padding
  printf("\nPadding 2: ");
  print_ascii_arr(tex1 -> PAD_2, get_j3dgraph_padding_size((tex1 -> PAD_2) - (tex1 -> START), true));
  
  // end of structure
  printf("\n### J3DGraph TEX1 section info end ###\n");
  return;
}

// TODO: research the BTI file format

//~ // EXTRACT_BMD_BDL_BTI() function
//~ // function to extract the BTI files contained in a BMD model
//~ void EXTRACT_MODEL_BTI(char * model_path)
//~ {  
  //~ printf("\nExtracting model textures...\n\n");
  
  //~ // create the Jmodel structure
  //~ Jmodel * MODEL = OPEN_MODEL(model_path);
  
  //~ // mask variables so they aren't that 
  //~ // long to read in this program block
  //~ byte *      M_DATA   = MODEL -> RAW_DT;
  //~ ENDIAN_T      M_ENDIAN = MODEL -> ENDIAN;
  //~ Jmodel_ptr_tb PTR_TB   = * MODEL -> PTR_TB;
  
  //~ // get the texture count
  //~ umax texture_count = GET_DATA_T(2, U_INT, M_DATA + PTR_TB.TEX_CNT, NULL, M_ENDIAN);
  
  //~ // loop through all of the texture names to get the one that has a larger size
  //~ umax max_str_size = 0;
  //~ for (smax_t i = 0; i < texture_count; i++)
  //~ {
    //~ umax str_pos = PTR_TB.TEX_STR_TB + GET_DATA_T(2, U_INT, M_DATA + PTR_TB.TEX_NAME_INF + (4 * i) + 2, NULL, M_ENDIAN);
    //~ umax tmp _str_size = get_str_byte_length(M_DATA + str_pos, 0);
    //~ if (tmp _str_size > max_str_size)
      //~ max_str_size = tmp _str_size;
  //~ }
  
  //~ // add to that the length of the model file path
  //~ // plus the size of the ".bti" extension string to be added
  //~ max_str_size += get_str_byte_length(model_path, 0) + 5;
  //~ // allocate space for the new string that will hold
  //~ // all of the new BTI file paths to be created
  //~ char * bti_file_path = allocate_memory(max_str_size, 1);
  //~ // get model directory path into bti_file_path and store
  //~ // the pointer to the last element written in bti_file_path
  //~ char * file_name_pos_ptr = get_file_dir(model_path, bti_file_path);
  
  //~ // loop through all of the texture header list to get the position of
  //~ // each texture data block and with that, the size of each texture file
  //~ umax * tex_data_pos = allocate_memory(texture_count, sizeof(umax));
  //~ umax * tex_size = allocate_memory(texture_count, sizeof(umax));
  //~ for (smax_t i = 0; i < texture_count; i++)
    //~ tex_data_pos[i] = GET_DATA_T(4, U_INT, M_DATA + PTR_TB.BTI_HEADER_LIST + (32 * i) + 28, NULL, M_ENDIAN) + (32 * i);
  
  //~ // sort tex_data_pos and get the actual valid
  //~ // filesizes for all BTIs on the BMD model
  //~ sort_array(tex_data_pos, texture_count, sizeof(umax), &comp_uint32);
  //~ for (smax_t i = 0; i < texture_count; i++)
    //~ // 32 is added because of the BTI header size
    //~ if (i == texture_count - 1)
      //~ tex_size[i] = 32 + PTR_TB.TEX_STR_TB - PTR_TB.BTI_HEADER_LIST - tex_data_pos[i];
    //~ else
      //~ tex_size[i] = 32 + tex_data_pos[i + 1] - tex_data_pos[i];
  
  //~ // go through all textures, get their names and
  //~ // their data to create the respective BTI files
  //~ for (smax_t i = 0; i < texture_count; i++)
  //~ {    
    //~ // texture name pointer on model data (M_DATA)
    //~ byte * tex_name_pos_ptr = M_DATA + PTR_TB.TEX_STR_TB +
      //~ GET_DATA_T(2, U_INT, M_DATA + PTR_TB.TEX_NAME_INF + 4 * i + 2, NULL, M_ENDIAN);  
    //~ // write texture name into file_name_pos_ptr (pointer to the last element written in bti_file_path)
    //~ char * ext_pos = join_strings(tex_name_pos_ptr, file_name_pos_ptr);
    //~ // write ".bti" into ext_pos (pointer to the last element written in bti_file_path after writing the bti file name)
    //~ join_strings(".bti", ext_pos);
    
    //~ // get BTI data position
    //~ umax bti_data_pos = GET_DATA_T(4, U_INT, M_DATA + PTR_TB.BTI_HEADER_LIST + (32 * i) + 28, NULL, M_ENDIAN) + (32 * i);
    
    //~ // variable to get the data position of the current bti texture on tex_data_pos
    //~ smax_t pos = 0;
    //~ while (tex_data_pos[pos] != bti_data_pos) pos++; // find BTI data position on tex_data_pos
    //~ while (tex_size[pos] == 32) pos++; // BTI size isn't the 32 ones (repeated data)
    
    //~ // allocate memory for the current bti data to be extracted
    //~ // and dump the data from the BMD BTI data on it
    //~ byte * bti_data = allocate_memory(tex_size[pos], 1);
    
    //~ // write bti_data
    //~ smax_t j = 0;
    //~ while (j < tex_size[pos])
    //~ {
      //~ // header
      //~ if (j >= 0 && j <= 31) {
        //~ // new offsets
        //~ if (j == 12) {
          //~ umax pallete_offset = 0x00000000; // wimgt compatibility (and afaik this should be 0)
          //~ j += WRITE_DATA_T(4, U_INT, &pallete_offset, bti_data + j, M_ENDIAN);
          //~ continue;
        //~ }
        //~ else if (j == 28) {
          //~ umax data_offset = 0x00000020; // seems like it is always this value
          //~ j += WRITE_DATA_T(4, U_INT, &data_offset, bti_data + j, M_ENDIAN);
          //~ continue;
        //~ }
        //~ // the rest of the header
        //~ else
          //~ bti_data[j] = M_DATA[PTR_TB.BTI_HEADER_LIST + (32 * i) + j];
      //~ }
      //~ // image data
      //~ else
        //~ bti_data[j] = M_DATA[PTR_TB.BTI_HEADER_LIST + tex_data_pos[pos] + j - 32];
      
      //~ // increase j
      //~ j++;
    //~ }
    
    //~ // create the BTI file and transfer the memory prepared data into the new BTI file
    //~ create_file(bti_file_path, tex_size[pos], bti_data);
    //~ free_memory(bti_data);
  //~ }
  
  //~ // free all memory used
  //~ CLOSE_MODEL(MODEL);
  //~ free_memory(bti_file_path);
  //~ free_memory(tex_data_pos);
  //~ free_memory(tex_size);
  //~ printf("\nDone!\n\n");
  
  //~ return;
//~ }
